
// Get the string that would represent this brick in a .bls file
function fxDtsBrick::gls_getLoadString(%brick) {
	if(!isObject(%brick)) { warn("fxDtsBrick::getLoadString - Brick " @ %brick @ "does not exist!"); return ""; }
	
	%data = %brick.getDatablock();
	
	%print = "";
	if(%data.hasPrint){
		%texture = getPrintTexture(%brick.getPrintId());
		%printPath = filePath(%texture);
		%underscorePos = strPos(%printPath, "_");
		%name = getSubStr(%printPath, %underscorePos + 1, strPos(%printPath, "_", 14) - 14) @ "/" @ fileBase(%texture);
		
		if($printNameTable[%name] !$= "")
			%print = %name;
	}
	
	%loadString =
		%data.uiName @ "\"" SPC
		%brick.getPosition() SPC
		%brick.getAngleID() SPC
		%brick.isBasePlate() SPC
		%brick.getColorID() SPC %print SPC %brick.getColorFXID() SPC %brick.getShapeFXID() SPC
		%brick.isRayCasting() SPC %brick.isColliding() SPC %brick.isRendering() @
		"\n";
	
	//if(%ownership && !$Server::LAN)
	//	%file.writeLine("+-OWNER " @ getBrickGroupFromObject(%brick).bl_id);
	
	%events = 1;
	if(%events){
		if(%brick.getName() !$= "")
			%loadString = %loadString @ "+-NTOBJECTNAME " @ %brick.getName() @ "\n";
		
		for(%b=0; %b<%brick.numEvents; %b++) {
			%targetClass = %brick.eventTargetIdx[%b] >= 0 ? getWord(getField($InputEvent_TargetListfxDTSBrick_[%brick.eventInputIdx[%b]], %brick.eventTargetIdx[%b]), 1) : "fxDtsBrick";
			%paramList = $OutputEvent_parameterList[%targetClass, %brick.eventOutputIdx[%b]];
			%params = "";
			
			for(%c=0;%c<4;%c++){
				if(firstWord(getField(%paramList, %c)) $= "dataBlock" && isObject(%brick.eventOutputParameter[%b, %c + 1]))
					%params = %params TAB %brick.eventOutputParameter[%b, %c + 1].getName();
				else
					%params = %params TAB %brick.eventOutputParameter[%b, %c + 1];
			}
			
			%loadString = %loadString @ "+-EVENT" TAB %b TAB %brick.eventEnabled[%b] TAB %brick.eventInput[%b] TAB %brick.eventDelay[%b] TAB %brick.eventTarget[%b] TAB %brick.eventNT[%b] TAB %brick.eventOutput[%b] @ %params @ "\n";
		}
	}
	
	if(isObject(%brick.emitter))
		%loadString = %loadString @ "+-EMITTER " @ %brick.emitter.emitter.uiName @ "\" " @ %brick.emitterDirection @ "\n";
	if(%brick.getLightID() >= 0)
		%loadString = %loadString @ "+-LIGHT " @ %brick.getLightID().getDataBlock().uiName @ "\" " @ "\n"; // Not sure if something else comes after the name
	if(isObject(%brick.item))
		%loadString = %loadString @ "+-ITEM " @ %brick.item.getDataBlock().uiName @ "\" " @ %brick.itemPosition SPC %brick.itemDirection SPC %brick.itemRespawnTime @ "\n";
	if(isObject(%brick.audioEmitter))
		%loadString = %loadString @ "+-AUDIOEMITTER " @ %brick.audioEmitter.getProfileID().uiName @ "\" " @ "\n"; // Not sure if something else comes after the name
	if(isObject(%brick.vehicleSpawnMarker))
		%loadString = %loadString @ "+-VEHICLE " @ %brick.vehicleSpawnMarker.uiName @ "\" " @ %brick.reColorVehicle @ "\n";
	
	return %loadString;
}

function gls_lsRotateVector(%vector, %angle) {
	switch(%angle % 4) {
		case 0: return %vector;
		case 1: return  getWord(%vector, 1) SPC -getWord(%vector, 0) SPC getWord(%vector, 2);
		case 2: return -getWord(%vector, 0) SPC -getWord(%vector, 1) SPC getWord(%vector, 2);
		case 3: return -getWord(%vector, 1) SPC  getWord(%vector, 0) SPC getWord(%vector, 2);
	}
}

function gls_lsTransformVector(%vector, %angle, %mirr) {
	if(getWord(%mirr, 0)) { %vector = -getWord(%vector, 0) SPC  getWord(%vector, 1) SPC  getWord(%vector, 2); }
	if(getWord(%mirr, 1)) { %vector =  getWord(%vector, 0) SPC -getWord(%vector, 1) SPC  getWord(%vector, 2); }
	if(getWord(%mirr, 2)) { %vector =  getWord(%vector, 0) SPC  getWord(%vector, 1) SPC -getWord(%vector, 2); }
	%vector = gls_lsRotateVector(%vector, %angle);
	return vectorAdd(%vector, "0 0 0");
}

function gls_lsTransformDirection(%dir, %steps, %mirr) {
	if(%dir > 1) {
		if(getWord(%mirr, 0) && %dir % 2 == 1 || getWord(%mirr, 1) && %dir % 2 == 0) { %dir += 2; }
		%dir = (%dir + %steps - 2) % 4 + 2;
	}
	else if(getWord(%mirr, 2)) { %dir = !%dir; }
	return %dir;
}

function gls_transformLoadLine(%line, %angleOffset, %mirr) {
	%firstWord = getWord(%line, 0);
	
	if(%firstWord $= "+-EVENT") {
		%eventNum = getField(%line, 1);
		%enabled = getField(%line, 2);
		%inputName = getField(%line, 3);
		%delay = getField(%line, 4);
		%targetName = getField(%line, 5);
		%NtName = getField(%line, 6);
		%outputName = getField(%line, 7);
		%par0 = getField(%line, 8);
		%par1 = getField(%line, 9);
		%par2 = getField(%line, 10);
		%par3 = getField(%line, 11);
		
		// Find input idx from name
		%inputIdx = inputEvent_GetInputEventIdx(%inputName);
		if(%inputIdx==-1) { warn("LOAD DUP: Input Event not found for name \"" @ %inputName @ "\""); }
		
		// Find target idx from name
		%targetIdx = inputEvent_GetTargetIndex("FxDTSBrick", %inputIdx, %targetName);
		if(%targetName==-1){ %targetClass = "FxDTSBrick"; }
		else { %targetList = getField($InputEvent_TargetList["FxDTSBrick", %inputIdx], %targetIdx); %targetClass = getWord(%targetList, 1); }
		
		%NTNameIdx = -1; // NT names handled elsewhere
		
		// Rotate relevant output events
		switch$(%outputName) {
			case "fireRelayUp"   : %dir =  0;
			case "fireRelayDown" : %dir =  1;
			case "fireRelayNorth": %dir =  2;
			case "fireRelayEast" : %dir =  3;
			case "fireRelaySouth": %dir =  4;
			case "fireRelayWest" : %dir =  5;
			default              : %dir = -1;
		}
		if(%dir >= 0) {
			%rotated = gls_lsTransformDirection(%dir, %angleOffset, %mirr);
			
			switch(%rotated) {
				case 0: %outputName = "fireRelayUp"   ;
				case 1: %outputName = "fireRelayDown" ;
				case 2: %outputName = "fireRelayNorth";
				case 3: %outputName = "fireRelayEast" ;
				case 4: %outputName = "fireRelaySouth";
				case 5: %outputName = "fireRelayWest" ;
			}
		}
		// Find output idx from name
		%outputIdx = outputEvent_GetOutputEventIdx(%targetClass, %outputName);
		if(%outputIdx==-1) { warn("LOAD DUP: Output Event not found for name \"" @ %outputName @ "\""); }
		
		// Apply params
		%paramList = $OutputEvent_ParameterList[%targetClass, %outputIdx];
		for(%j = 0; %j<=3; %j++){
			%paramInfo = getField(%paramList, %j);
			%paramType = getWord(%paramInfo, 0);
			%param = %par[%j];
			
			// Apply / rotate relevant params
			if(%paramType $= "Datablock" && %param !$= "-1") {
				
			} else if(%paramType $= "vector") {
				%param = gls_lsTransformVector(%param, %angleOffset, %mirr);
			} else if(%paramType $= "list") {
				%val = getWord(%paramInfo, %param*2+1);
				switch$(%val) {
					case "Up"   : %dir = 0;
					case "Down" : %dir = 1;
					case "North": %dir = 2;
					case "East" : %dir = 3;
					case "South": %dir = 4;
					case "West" : %dir = 5;
					default: %dir = -1;
				}
				if(%dir>=0) {
					switch(gls_lsTransformDirection(%dir, %angleOffset, %mirr)) {
						case 0: %val = "Up"   ;
						case 1: %val = "Down" ;
						case 2: %val = "North";
						case 3: %val = "East" ;
						case 4: %val = "South";
						case 5: %val = "West" ;
					}
				}
				for(%l = 1; %l < getWordCount(%paramInfo); %l += 2) {
					if(getWord(%paramInfo, %l) $= %val) {
						%param = getWord(%paramInfo, %l+1);
						break;
					}
				}
			}
			
			%par[%j] = %param;
		}
		
		%line =
			"+-EVENT" TAB
			%eventNum TAB
			%enabled TAB
			%inputName TAB
			%delay TAB
			%targetName TAB
			%NtName TAB
			%outputName TAB
			%par0 TAB
			%par1 TAB
			%par2 TAB
			%par3;
		
	} else if(%firstWord $= "+-EMITTER") {
		%line = getSubStr(%line, 10, strlen(%line) - 10.0);
		%pos = strpos(%line, "\"");
		%dbName = getSubStr(%line, 0, %pos);
		
		%line = getSubStr(%line, %pos + 2.0, strlen(%line) - %pos - 2.0);
		%dir = getWord(%line, 0);
		
		%dir = gls_lsTransformDirection(%dir, %angleOffset, %mirr);
		
		%line = "+-EMITTER" SPC %dbName @ "\"" SPC %dir;
	} else if(%firstWord $= "+-ITEM") {
		%line = getSubStr(%line, 7, strlen(%line) - 7.0);
		%pos = strpos(%line, "\"");
		%dbName = getSubStr(%line, 0, %pos);
		
		%line = getSubStr(%line, %pos + 2.0, strlen(%line) - %pos - 2.0);
		%pos = getWord(%line, 0);
		%dir = getWord(%line, 1);
		%respawnTime = getWord(%line, 2);
		
		%pos = gls_lsTransformDirection(%pos, %angleOffset, %mirr);
		%dir = gls_lsTransformDirection(%dir, %angleOffset, %mirr);
		
		%line = "+-ITEM" SPC %dbName @ "\"" SPC %pos SPC %dir SPC %respawnTime;
	}
	
	return %line;
}

function gls_lbRotateBrick(%datablock, %bAngle, %mirr) {
	if(getWord(%mirr, 0)) {
		//Handle symmetries
		switch($ND::Symmetry[%datablock]) {
			case 0: if(%db = $ND::SymmetryXDatablock[%datablock]) {
				%datablock = %db;
				%bAngle = (%bAngle + $ND::SymmetryXOffset[%datablock]) % 4;
				//Pair is made on X, so apply mirror logic for X afterwards
				if(%bAngle % 2 == 1) { %bAngle = (%bAngle + 2) % 4; }
			}
			//Do nothing for fully symmetric
			//X symmetric - rotate 180 degrees if brick is angled 90 or 270 degrees
			case 2: if(%bAngle % 2 == 1) { %bAngle = (%bAngle + 2) % 4; }
			//Y symmetric - rotate 180 degrees if brick is angled 0 or 180 degrees
			case 3: if(%bAngle % 2 == 0) { %bAngle = (%bAngle + 2) % 4; }
			//X+Y symmetric - rotate 90 degrees
			case 4: if(%bAngle % 2 == 0) { %bAngle = (%bAngle + 1) % 4; } else { %bAngle = (%bAngle + 3) % 4; }
			//X-Y symmetric - rotate -90 degrees
			case 5: if(%bAngle % 2 == 0) { %bAngle = (%bAngle + 3) % 4; } else { %bAngle = (%bAngle + 1) % 4; }
		}
	}
	if(getWord(%mirr, 1)) {
		//Handle symmetries
		switch($ND::Symmetry[%datablock])
		{
			//Asymmetric
			case 0: if(%db = $ND::SymmetryXDatablock[%datablock]) {
				%datablock = %db;
				%bAngle = (%bAngle + $ND::SymmetryXOffset[%datablock]) % 4;
				//Pair is made on X, so apply mirror logic for X afterwards
				if(%bAngle % 2 == 0) { %bAngle = (%bAngle + 2) % 4; }
			}
			//Do nothing for fully symmetric
			//X symmetric - rotate 180 degrees if brick is angled 90 or 270 degrees
			case 2: if(%bAngle % 2 == 0) { %bAngle = (%bAngle + 2) % 4; }
			//Y symmetric - rotate 180 degrees if brick is angled 0 or 180 degrees
			case 3: if(%bAngle % 2 == 1) { %bAngle = (%bAngle + 2) % 4; }
			//X+Y symmetric - rotate 90 degrees
			case 4: if(%bAngle % 2 == 1) { %bAngle = (%bAngle + 1) % 4; } else { %bAngle = (%bAngle + 3) % 4; }
			//X-Y symmetric - rotate -90 degrees
			case 5: if(%bAngle % 2 == 1) { %bAngle = (%bAngle + 3) % 4; } else { %bAngle = (%bAngle + 1) % 4; }
		}
	}
	if(getWord(%mirr, 2)) {
		//Change datablock if asymmetric
		if(!$ND::SymmetryZ[%datablock]) {
			if(%db = $ND::SymmetryZDatablock[%datablock]) {
				%datablock = %db;
				%bAngle = (%bAngle + $ND::SymmetryZOffset[%datablock]) % 4;
			}
		}
	}
	return %datablock SPC %bAngle;
}

function gls_loadSaveLine(%line, %client, %lastLoadedBrick, %brickgroup, %firstpos, %positionOffset, %angleOffset, %mirr) {
	%firstWord = getWord(%line, 0);
	
	if(%firstWord $= "+-EVENT") {
		if(isObject(%lastLoadedBrick)) {
			%enabled = getField(%line, 2);
			%inputName = getField(%line, 3);
			%delay = getField(%line, 4);
			%targetName = getField(%line, 5);
			%NtName = getField(%line, 6);
			%outputName = getField(%line, 7);
			%par0 = getField(%line, 8);
			%par1 = getField(%line, 9);
			%par2 = getField(%line, 10);
			%par3 = getField(%line, 11);
			
			// Find input idx from name
			%inputIdx = inputEvent_GetInputEventIdx(%inputName);
			if(%inputIdx==-1) { warn("LOAD DUP: Input Event not found for name \"" @ %inputName @ "\""); }
			
			// Find target idx from name
			%targetIdx = inputEvent_GetTargetIndex("FxDTSBrick", %inputIdx, %targetName);
			if(%targetName==-1){ %targetClass = "FxDTSBrick"; }
			else { %targetList = getField($InputEvent_TargetList["FxDTSBrick", %inputIdx], %targetIdx); %targetClass = getWord(%targetList, 1); }
			
			%NTNameIdx = -1; // NT names handled elsewhere
			
			// Rotate relevant output events
			switch$(%outputName) {
				case "fireRelayUp"   : %dir =  0;
				case "fireRelayDown" : %dir =  1;
				case "fireRelayNorth": %dir =  2;
				case "fireRelayEast" : %dir =  3;
				case "fireRelaySouth": %dir =  4;
				case "fireRelayWest" : %dir =  5;
				default              : %dir = -1;
			}
			if(%dir >= 0) {
				%rotated = gls_lsTransformDirection(%dir, %angleOffset, %mirr);
				%outputIdx += %rotated - %dir;
				
				switch(%rotated) {
					case 0: %outputName = "fireRelayUp"   ;
					case 1: %outputName = "fireRelayDown" ;
					case 2: %outputName = "fireRelayNorth";
					case 3: %outputName = "fireRelayEast" ;
					case 4: %outputName = "fireRelaySouth";
					case 5: %outputName = "fireRelayWest" ;
				}
			}
			// Find output idx from name
			%outputIdx = outputEvent_GetOutputEventIdx(%targetClass, %outputName);
			if(%outputIdx==-1) { warn("LOAD DUP: Output Event not found for name \"" @ %outputName @ "\""); }
			
			// Apply params
			%paramList = $OutputEvent_ParameterList[%targetClass, %outputIdx];
			for(%j = 0; %j<=3; %j++){
				%paramInfo = getField(%paramList, %j);
				%paramType = getWord(%paramInfo, 0);
				%param = %par[%j];
				
				// Apply / rotate relevant params
				if(%paramType $= "Datablock" && %param !$= "-1") {
					%param = nameToId(%param);
					if(!isObject(%param)) { warn("LOAD DUP: Datablock not found for event " @ %outputName @ " -> " @ %param); %param = 0; }
				} else if(%paramType $= "vector") {
					%param = gls_lsTransformVector(%param, %angleOffset, %mirr);
				} else if(%paramType $= "list") {
					%val = getWord(%paramInfo, %param*2+1);
					switch$(%val) {
						case "Up"   : %dir = 0;
						case "Down" : %dir = 1;
						case "North": %dir = 2;
						case "East" : %dir = 3;
						case "South": %dir = 4;
						case "West" : %dir = 5;
						default: %dir = -1;
					}
					if(%dir>=0) {
						switch(gls_lsTransformDirection(%dir, %angleOffset, %mirr)) {
							case 0: %val = "Up"   ;
							case 1: %val = "Down" ;
							case 2: %val = "North";
							case 3: %val = "East" ;
							case 4: %val = "South";
							case 5: %val = "West" ;
						}
					}
					for(%l = 1; %l < getWordCount(%paramInfo); %l += 2) {
						if(getWord(%paramInfo, %l) $= %val) {
							%param = getWord(%paramInfo, %l+1);
							break;
						}
					}
				}
				
				%par[%j] = %param;
			}
			
			// Apply events
			%client.wrenchBrick = %lastLoadedBrick;
			serverCmdAddEvent(%client, %enabled, %inputIdx, %delay, %targetIdx, %NTNameIdx, %outputIdx, %par0, %par1, %par2, %par3);
			%lastLoadedBrick.eventNT[%lastLoadedBrick.numEvents-1] = %NtName;
		}
	} else if(%firstWord $= "+-NTOBJECTNAME") {
		if(isObject(%lastLoadedBrick)){
			%name = getWord(%line, 1);
			%lastLoadedBrick.setNTObjectName(%name);
		}
	} else if(%firstWord $= "+-LIGHT") {
		if(isObject(%lastLoadedBrick)) {
			%line = getSubStr(%line, 8, strlen(%line) - 8.0);
			%pos = strpos(%line, "\"");
			%dbName = getSubStr(%line, 0, %pos);
			
			%db = $uiNameTable_Lights[%dbName];
			if(!isObject(%db)) {
				warn("WARNING: could not find light datablock for uiname " @ %dbName @ "");
				%db = $uiNameTable_Lights["Player\'s Light"];
			}
			
			if(strlen(%line) - %pos - 2.0 >= 0.0) {
				%line = getSubStr(%line, %pos + 2.0, strlen(%line) - %pos - 2.0);
				%enabled = %line;
				if(%enabled $= "\"") { %enabled = 1; }
			} else { %enabled = 1; }
			
			%quotaObject = getQuotaObjectFromBrick(%lastLoadedBrick);
			setCurrentQuotaObject(%quotaObject);
			%lastLoadedBrick.setLight(%db);
			if(isObject(%lastLoadedBrick.light)) { %lastLoadedBrick.light.setEnable(%enabled); }
			clearCurrentQuotaObject();
		}
	} else if(%firstWord $= "+-EMITTER") {
		if(isObject(%lastLoadedBrick)) {
			%line = getSubStr(%line, 10, strlen(%line) - 10.0);
			%pos = strpos(%line, "\"");
			%dbName = getSubStr(%line, 0, %pos);
			
			if(%dbName $= "NONE") { %db = 0; } else { %db = $uiNameTable_Emitters[%dbName]; }
			if(!isObject(%db)) { warn("WARNING: could not find emitter datablock for uiname " @ %dbName @ ""); }
			
			%line = getSubStr(%line, %pos + 2.0, strlen(%line) - %pos - 2.0);
			%dir = getWord(%line, 0);
			
			%dir = gls_lsTransformDirection(%dir, %angleOffset, %mirr);
			
			%quotaObject = getQuotaObjectFromBrick(%lastLoadedBrick);
			setCurrentQuotaObject(%quotaObject);
			if(isObject(%db)){ %lastLoadedBrick.setEmitter(%db); }
			%lastLoadedBrick.setEmitterDirection(%dir);
			clearCurrentQuotaObject();
		}
	} else if(%firstWord $= "+-ITEM") {
		if(isObject(%lastLoadedBrick)) {
			%line = getSubStr(%line, 7, strlen(%line) - 7.0);
			%pos = strpos(%line, "\"");
			%dbName = getSubStr(%line, 0, %pos);
			
			if(%dbName $= "NONE") { %db = 0; } else { %db = $uiNameTable_Items[%dbName]; }
			if(%dbName !$= "NONE" && !isObject(%db)) { warn("WARNING: could not find item datablock for uiname " @ %dbName @ ""); }
			
			%line = getSubStr(%line, %pos + 2.0, strlen(%line) - %pos - 2.0);
			%pos = getWord(%line, 0);
			%dir = getWord(%line, 1);
			%respawnTime = getWord(%line, 2);
			
			%pos = gls_lsTransformDirection(%pos, %angleOffset, %mirr);
			%dir = gls_lsTransformDirection(%dir, %angleOffset, %mirr);
			
			%quotaObject = getQuotaObjectFromBrick(%lastLoadedBrick);
			setCurrentQuotaObject(%quotaObject);
			if(isObject(%db)){ %lastLoadedBrick.setItem(%db); }
			%lastLoadedBrick.setItemDirection(%dir);
			%lastLoadedBrick.setItemPosition(%pos);
			%lastLoadedBrick.setItemRespawntime(%respawnTime);
			clearCurrentQuotaObject();
		}
	} else if(%firstWord $= "+-AUDIOEMITTER") {
		if(isObject(%lastLoadedBrick)) {
			%line = getSubStr(%line, 15, strlen(%line) - 15.0);
			%pos = strpos(%line, "\"");
			%dbName = getSubStr(%line, 0, %pos);
			%db = $uiNameTable_Music[%dbName];
			
			if(!isObject(%db)) { warn("WARNING: could not find music datablock for uiname " @ %dbName @ ""); }
			
			%quotaObject = getQuotaObjectFromBrick(%lastLoadedBrick);
			setCurrentQuotaObject(%quotaObject);
			%lastLoadedBrick.setSound(%db);
			clearCurrentQuotaObject();
		}
	} else if(%firstWord $= "+-VEHICLE") {
		if(isObject(%lastLoadedBrick)) {
			%line = getSubStr(%line, 10, strlen(%line) - 10.0);
			%pos = strpos(%line, "\"");
			%dbName = getSubStr(%line, 0, %pos);
			%db = $uiNameTable_Vehicle[%dbName];
			
			if(!isObject(%db)) { warn("WARNING: could not find vehicle datablock for uiname " @ %dbName @ ""); }
			
			%line = getSubStr(%line, %pos + 2.0, strlen(%line) - %pos - 2.0);
			%recolorVehicle = getWord(%line, 0);
			
			%quotaObject = getQuotaObjectFromBrick(%lastLoadedBrick);
			setCurrentQuotaObject(%quotaObject);
			%lastLoadedBrick.setVehicle(%db);
			%lastLoadedBrick.setReColorVehicle(%recolorVehicle);
			clearCurrentQuotaObject();
		}
	} else if(%firstWord $= "+-OWNER") {
		
	} else {
		if(getBrickCount() >= getBrickLimit()){ MessageAll('', 'Brick limit reached (%1)', getBrickLimit()); return; }
		
		%quotePos = strstr(%line, "\"");
		if(%quotePos <= 0.0) {
			error("ERROR: loadSaveAtPos() - Bad line " @ %line @ " - expected brick line but found no uiname");
		} else {
			%uiName = getSubStr(%line, 0, %quotePos);
			
			if(%uiName !$= "ND_SIZE" && %uiName !$= "ND_TREE") {
				%db = $uiNameTable[%uiName];
				
				%line = getSubStr(%line, %quotePos + 2.0, 9999);
				
				%pos = getWords(%line, 0, 2);
				%angId = getWord(%line, 3);
				%isBaseplate = getWord(%line, 4);
				%colorId = getWord(%line, 5);
				
				%printName = getWord(%line, 6);
				if(strpos(%printName, "/") != -1.0) {
					%printName = fileBase(%printName);
					%aspectRatio = %db.printAspectRatio;
					%printIDName = %aspectRatio @ "/" @ %printName;
					%printId = $printNameTable[%printIDName];
					if(%printId $= "") { %printIDName = "Letters/" @ %printName; %printId = $printNameTable[%printIDName]; }
					if(%printId $= "") { %printId = $printNameTable["Letters/-space"]; }
				} else { %printId = $printNameTable[%printName]; }
				
				%colorFX = getWord(%line, 7);
				%shapeFX = getWord(%line, 8);
				%rayCasting = getWord(%line, 9);
				%collision = getWord(%line, 10);
				%rendering = getWord(%line, 11);
				
				if(isObject(%db)) {
					//if(%firstpos $= "") { %firstpos = vectorAdd(%pos, "0 0 " @ (-%db.brickSizeZ*0.2/2)); }
					
					%rotatedb = gls_lbRotateBrick(%db, %angId, %mirr);
					%db = getWord(%rotatedb, 0);
					%angId = getWord(%rotatedb, 1);
					
					//%pos = vectorSub(%pos, %firstpos);
					
					%pos = gls_lsTransformVector(%pos, %angleOffset, %mirr);
					
					%pos = vectorAdd(%pos, %positionOffset);
					%angId = (%angId + %angleOffset) % 4;
					
					%trans = %pos;
					
					if(%angId==0.0) {
						%trans = %trans SPC " 1 0 0 0";
					} else if(%angId==1.0) {
						%trans = %trans SPC " 0 0 1" SPC $piOver2;
					} else if(%angId==2.0) {
						%trans = %trans SPC " 0 0 1" SPC $pi;
					} else if(%angId==3.0) {
						%trans = %trans SPC " 0 0 -1" SPC $piOver2;
					}
					
					%b = new fxDTSBrick() {
						dataBlock = %db;
						angleID = %angId;
						isBasePlate = %isBaseplate;
						colorID = %colorId;
						printID = %printId;
						colorFxID = %colorFX;
						shapeFxID = %shapeFX;
						isPlanted = 1;
					};
					
					if(!isObject(%brickgroup)) {
						error("ERROR: loadSaveAtPos() - %brickgroup does not exist!");
						MessageAll('', "ERROR: loadSaveAtPos() - %brickgroup does not exist!");
						%b.delete();
						return;
					}
					
					%b.setTransform(%trans);
					%b.trustCheckFinished();
					
					%lastLoadedBrick = %b;
					
					//This will call ::onLoadPlant instead of ::onPlant
					%prev1 = $Server_LoadFileObj;
					%prev2 = $LastLoadedBrick;
					$Server_LoadFileObj = %b;
					$LastLoadedBrick = %b;
					//Add to brickgroup
					%brickGroup.add(%b);
					//Attempt plant
					%err = %b.plant();
					//Restore variable
					$Server_LoadFileObj = %prev1;
					$LastLoadedBrick = %prev2;
					
					if(%err==1.0 || %err==3.0 || %err==5.0) {
						%failureCount = %failureCount + 1.0;
						%b.delete();
						%lastLoadedBrick = 0;
					} else {
						if(%rayCasting !$= ""){
							%b.setRayCasting(%rayCasting);
						}
						if(%collision !$= ""){
							%b.setColliding(%collision);
						}
						if(%rendering !$= ""){
							%b.setRendering(%rendering);
						}
						
						%b.client = %client;
						
						%newbrick = true;
					}
				} else {
					if(!%missingBrickWarned[%uiName]) {
						warn("WARNING: loadBricks() - DataBlock not found for brick named ", %uiName, "");
						%missingBrickWarned[%uiName] = 1;
					}
					%lastLoadedBrick = 0;
				}
			}
		}
	}
	return %lastLoadedBrick;
}

function gls_init() {
	$gls_client = findClientByName("Redo");
	$gls_brickGroup = $gls_client.brickGroup;
	$gls_lastLoadedBrick = 0;
}
function gls_loadLoadStringLine(%line) {
	%result = gls_loadSaveLine(%line, $gls_client, $gls_lastLoadedBrick, $gls_brickGroup, "0 0 0", "0 0 0", 0, "0 0 0");
	$gls_lastLoadedBrick = %result;
	return %result;
}
